home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / hoobie / listhosts.c < prev    next >
C/C++ Source or Header  |  2001-11-06  |  29KB  |  1,296 lines

  1. /*
  2.  * Copyright (c) 1986 Regents of the University of California
  3.  * All Rights Reserved
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that this notice is preserved and that due credit is given
  7.  * to the University of California at Berkeley. The name of the University
  8.  * may not be used to endorse or promote products derived from this
  9.  * software without specific prior written permission. This software
  10.  * is provided ``as is'' without express or implied warranty.
  11.  */
  12.  
  13. /*
  14.  * Actually, this program is from Rutgers University, however it is 
  15.  * based on nslookup and other pieces of named tools, so it needs
  16.  * that copyright notice.
  17.  *
  18.  * To compile on a Sun, use the resolv library:
  19.  *    cc -O -o host host.c -lresolv
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include <sys/types.h>
  24. #include <arpa/nameser.h>
  25. #include <netdb.h>
  26. #include <sys/socket.h>
  27. #include <netinet/in.h>
  28. #include <resolv.h>
  29. #include <sys/param.h>
  30. #include <strings.h>
  31. #include <ctype.h>
  32.  
  33. extern int h_errno;
  34.  
  35. #define NUMMX 50
  36.  
  37. #define  SUCCESS        0
  38. #define  TIME_OUT        -1
  39. #define  NO_INFO         -2
  40. #define  ERROR             -3
  41. #define  NONAUTH         -4
  42.  
  43. #define NAME_LEN 256
  44.  
  45. #ifndef T_TXT
  46. #define T_TXT 16
  47. #endif
  48. #ifndef NO_DATA
  49. #define NO_DATA NO_ADDRESS
  50. #endif
  51. #ifndef C_HS
  52. #define C_HS 4
  53. #endif
  54.  
  55. int sockFD;
  56. FILE *filePtr;
  57. char *DecodeError();
  58.  
  59. struct state orig;
  60. extern struct state _res;
  61. static char *cname = NULL;
  62. extern char *inet_ntoa();
  63. extern    char *sprintf();
  64. extern u_long inet_addr();
  65. int getclass = C_IN;
  66. int gettype;
  67. int verbose = 0;
  68. int list = 0;
  69. int server_specified = 0;
  70.  
  71. char *pr_class();
  72. char *pr_rr();
  73. char *pr_cdname();
  74. char *pr_type();
  75.  
  76. main(c, v)
  77.     char **v;
  78. {
  79.     unsigned addr;
  80.     register struct hostent *hp;
  81.     register char *s;
  82.     register inverse = 0;
  83.     register waitmode = 0;
  84.     char *oldcname;
  85.     int ncnames;
  86.  
  87.     res_init();
  88.     _res.retrans = 5;
  89.  
  90.     if (c < 2) {
  91.         fprintf(stderr, "Usage: host [-w] [-v] [-r] [-d] [-t querytype] [-c class] [-a] host [server]\n  -w to wait forever until reply\n  -v for verbose output\n  -r to disable recursive processing\n  -d to turn on debugging output\n  -t querytype to look for 
  92. a specific type of information\n  -c class to look for non-Internet data\n  -a is equivalent to '-v -t *'\n");
  93.         exit(1);
  94.     }
  95.     while (c > 2 && v[1][0] == '-') {
  96.         if (strcmp (v[1], "-w") == 0) {
  97.             _res.retry = 1;
  98.             _res.retrans = 15;
  99.             waitmode = 1;
  100.             v++;
  101.             c--;
  102.         }
  103.         else if (strcmp (v[1], "-r") == 0) {
  104.             _res.options &= ~RES_RECURSE;
  105.             v++;
  106.             c--;
  107.         }
  108.         else if (strcmp (v[1], "-d") == 0) {
  109.             _res.options |= RES_DEBUG;
  110.             v++;
  111.             c--;
  112.         }
  113.         else if (strcmp (v[1], "-v") == 0) {
  114.             verbose = 1;
  115.             v++;
  116.             c--;
  117.         }
  118.         else if (strcmp (v[1], "-l") == 0) {
  119.             list = 1;
  120.             v++;
  121.             c--;
  122.         }
  123.         else if (strncmp (v[1], "-t", 2) == 0) {
  124.             v++;
  125.             c--;
  126.             gettype = parsetype(v[1]);
  127.             v++;
  128.             c--;
  129.         }
  130.         else if (strncmp (v[1], "-c", 2) == 0) {
  131.             v++;
  132.             c--;
  133.             getclass = parseclass(v[1]);
  134.             v++;
  135.             c--;
  136.         }
  137.         else if (strcmp (v[1], "-a") == 0) {
  138.             verbose = 1;
  139.             gettype = T_ANY;
  140.             v++;
  141.             c--;
  142.         }        
  143.         }
  144.     if (c > 2) {
  145.         s = v[2];
  146.         server_specified++;
  147.         
  148.         addr = inet_addr(s);
  149.         if (addr == -1) {
  150.           hp = gethostbyname(s);
  151.           if (hp == NULL) {
  152.             fprintf(stderr,"Error in looking up server name:\n");
  153.             hperror(h_errno);
  154.             exit(1);
  155.           }
  156.           _res.nsaddr.sin_addr = *(struct in_addr *)hp->h_addr;
  157.           printf("Using domain server:\n");
  158.           printanswer(hp);
  159.         }
  160.         else {
  161.           _res.nsaddr.sin_family = AF_INET;
  162.           _res.nsaddr.sin_addr.s_addr = addr;
  163.           _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
  164.           printf("Using domain server %s:\n",
  165.              inet_ntoa(_res.nsaddr.sin_addr));
  166.         }
  167.           }
  168.     if (strcmp (v[1], ".") == 0)
  169.       addr = -1;
  170.     else
  171.       addr = inet_addr(v[1]);
  172.     hp = NULL;
  173.     h_errno = TRY_AGAIN;
  174. /*
  175.  * we handle default domains ourselves, thank you
  176.  */
  177.     _res.options &= ~RES_DEFNAMES;
  178.  
  179.         if (list)
  180.       exit(ListHosts(v[1], gettype ? gettype : T_A));
  181.     oldcname = NULL;
  182.     ncnames = 5;
  183.     while (hp == NULL && h_errno == TRY_AGAIN) {
  184.       if (addr == -1) {
  185.           cname = NULL;
  186.           if (oldcname == NULL)
  187.         hp = (struct hostent *)gethostinfo(v[1]);
  188.           else
  189.         hp = (struct hostent *)gethostinfo(oldcname);
  190.           if (cname) {
  191.         if (ncnames-- == 0) {
  192.           printf("Too many cnames.  Possible loop.\n");
  193.           exit(1);
  194.         }
  195.         oldcname = cname;
  196.         hp = NULL;
  197.         h_errno = TRY_AGAIN;
  198.         continue;
  199.           }
  200.       }
  201.       else {
  202.         hp = gethostbyaddr(&addr, 4, AF_INET);
  203.         if (hp)
  204.           printanswer(hp);
  205.       }
  206.       if (!waitmode)
  207.         break;
  208.     }
  209.  
  210.     if (hp == NULL) {
  211.       hperror(h_errno);
  212.       exit(1);
  213.     }
  214.  
  215.     exit(0);
  216.  
  217. }
  218.  
  219. parsetype(s)
  220.     char *s;
  221. {
  222. if (strcmp(s,"a") == 0)
  223.   return(1);
  224. if (strcmp(s,"ns") == 0)
  225.   return(2);
  226. if (strcmp(s,"md") == 0)
  227.   return(3);
  228. if (strcmp(s,"mf") == 0)
  229.   return(4);
  230. if (strcmp(s,"cname") == 0)
  231.   return(5);
  232. if (strcmp(s,"soa") == 0)
  233.   return(6);
  234. if (strcmp(s,"mb") == 0)
  235.   return(7);
  236. if (strcmp(s,"mg") == 0)
  237.   return(8);
  238. if (strcmp(s,"mr") == 0)
  239.   return(9);
  240. if (strcmp(s,"null") == 0)
  241.   return(10);
  242. if (strcmp(s,"wks") == 0)
  243.   return(11);
  244. if (strcmp(s,"ptr") == 0)
  245.   return(12);
  246. if (strcmp(s,"hinfo") == 0)
  247.   return(13);
  248. if (strcmp(s,"minfo") == 0)
  249.   return(14);
  250. if (strcmp(s,"mx") == 0)
  251.   return(15);
  252. if (strcmp(s,"txt") == 0)    /* Roy */
  253.   return(T_TXT);        /* Roy */
  254. if (strcmp(s,"uinfo") == 0)
  255.   return(100);
  256. if (strcmp(s,"uid") == 0)
  257.   return(101);
  258. if (strcmp(s,"gid") == 0)
  259.   return(102);
  260. if (strcmp(s,"unspec") == 0)
  261.   return(103);
  262. if (strcmp(s,"any") == 0)
  263.   return(255);
  264. if (strcmp(s,"*") == 0)
  265.   return(255);
  266. if (atoi(s))
  267.   return(atoi(s));
  268. fprintf(stderr, "Invalid query type: %s\n", s);
  269. exit(2);
  270. }
  271.  
  272. parseclass(s)
  273.     char *s;
  274. {
  275. if (strcmp(s,"in") == 0)
  276.   return(C_IN);
  277. if (strcmp(s,"hs") == 0)
  278.   return(C_HS);
  279. if (strcmp(s,"any") == 0)
  280.   return(C_ANY);
  281. if (atoi(s))
  282.   return(atoi(s));
  283. fprintf(stderr, "Invalid query class: %s\n", s);
  284. exit(2);
  285. }
  286.  
  287. printanswer(hp)
  288.     register struct hostent *hp;
  289. {
  290.     register char **cp;
  291.     register long **hptr;
  292.  
  293.     printf("Name: %s\n", hp->h_name);
  294.     printf("Address:");
  295.     for (hptr = (long **)hp->h_addr_list; *hptr; hptr++)
  296.       printf(" %s", inet_ntoa(*(struct in_addr *)*hptr));
  297.     printf("\nAliases:");
  298.     for (cp = hp->h_aliases; cp && *cp && **cp; cp++)
  299.         printf(" %s", *cp);
  300.     printf("\n\n");
  301. }
  302.  
  303. hperror(errno) 
  304. int errno;
  305. {
  306. switch(errno) {
  307.     case HOST_NOT_FOUND:
  308.         fprintf(stderr,"Host not found.\n");
  309.         break;
  310.     case TRY_AGAIN:
  311.         fprintf(stderr,"Host not found, try again.\n");
  312.         break;
  313.     case NO_RECOVERY:
  314.         fprintf(stderr,"No recovery, Host not found.\n");
  315.         break;
  316.     case NO_ADDRESS:
  317.         fprintf(stderr,"There is an entry for this host, but it doesn't have an Internet address.\n");
  318.         break;
  319.     }
  320. }
  321.  
  322.  
  323. typedef union {
  324.     HEADER qb1;
  325.     char qb2[PACKETSZ];
  326. } querybuf;
  327.  
  328. static char hostbuf[BUFSIZ+1];
  329.  
  330.  
  331. char *hostalias();
  332.  
  333. gethostinfo(name)
  334.     char *name;
  335. {
  336.     register char *cp, **domain;
  337.     int n;
  338.     int hp;
  339.     int nDomain;
  340.  
  341.     if (strcmp(name, ".") == 0)
  342.         return(getdomaininfo(name, NULL));
  343.     for (cp = name, n = 0; *cp; cp++)
  344.         if (*cp == '.')
  345.             n++;
  346.     if (n && cp[-1] == '.') {
  347.         if (cp[-1] == '.')
  348.             cp[-1] = 0;
  349.         hp = getdomaininfo(name, (char *)NULL);
  350.         if (cp[-1] == 0)
  351.             cp[-1] = '.';
  352.         return (hp);
  353.     }
  354.     if (n == 0 && (cp = hostalias(name))) {
  355.             if (verbose)
  356.             printf("Aliased to \"%s\"\n", cp);
  357.         _res.options |= RES_DEFNAMES;      
  358.         return (getdomaininfo(cp, (char *)NULL));
  359.     }
  360. #ifdef MAXDS
  361.     for (nDomain = 0;
  362.          _res.defdname_list[nDomain][0] != 0;
  363.          nDomain++) {
  364.         for (domain = _res.dnsrch_list[nDomain]; *domain; domain++) {
  365.             if (verbose)
  366.             printf("Trying domain \"%s\"\n", *domain);
  367.         hp = getdomaininfo(name, *domain);
  368.         if (hp)
  369.             return (hp);
  370.         }
  371.     }
  372. #else
  373.     for (domain = _res.dnsrch; *domain; domain++) {
  374.       if (verbose)
  375.         printf("Trying domain \"%s\"\n", *domain);
  376.       hp = getdomaininfo(name, *domain);
  377.       if (hp)
  378.         return (hp);
  379.     }
  380. #endif
  381.     if (h_errno != HOST_NOT_FOUND ||
  382.        (_res.options & RES_DNSRCH) == 0)
  383.         return (NULL);
  384.     if (verbose)
  385.         printf("Trying null domain\n");
  386.     return (getdomaininfo(name, (char *)NULL));
  387. }
  388.  
  389. getdomaininfo(name, domain)
  390.     char *name, *domain;
  391. {
  392.   int val1, val2;
  393.  
  394.   if (gettype)
  395.     return getinfo(name, domain, gettype);
  396.   else {
  397.     val1 = getinfo(name, domain, T_A);
  398.     if (cname || verbose)
  399.       return val1;
  400.     val2 = getinfo(name, domain, T_MX);
  401.     return val1 || val2;
  402.   }
  403. }
  404.  
  405. getinfo(name, domain, type)
  406.     char *name, *domain;
  407. {
  408.  
  409.     HEADER *hp;
  410.     char *eom, *bp, *cp;
  411.     querybuf buf, answer;
  412.     int n, n1, i, j, nmx, ancount, nscount, arcount, qdcount, buflen;
  413.     u_short pref, class;
  414.     char host[2*MAXDNAME+2];
  415.  
  416.     if (domain == NULL)
  417.         (void)sprintf(host, "%.*s", MAXDNAME, name);
  418.     else
  419.         (void)sprintf(host, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain);
  420.  
  421.     n = res_mkquery(QUERY, host, getclass, type, (char *)NULL, 0, NULL,
  422.         (char *)&buf, sizeof(buf));
  423.     if (n < 0) {
  424.         if (_res.options & RES_DEBUG)
  425.             printf("res_mkquery failed\n");
  426.         h_errno = NO_RECOVERY;
  427.         return(0);
  428.     }
  429.     n = res_send((char *)&buf, n, (char *)&answer, sizeof(answer));
  430.     if (n < 0) {
  431.         if (_res.options & RES_DEBUG)
  432.             printf("res_send failed\n");
  433.         h_errno = TRY_AGAIN;
  434.         return (0);
  435.     }
  436.     eom = (char *)&answer + n;
  437.     return(printinfo(&answer, eom, T_ANY, 0));
  438.       }
  439.  
  440. printinfo(answer, eom, filter, isls)
  441.     querybuf *answer;
  442.     char *eom;
  443.         int filter;
  444.         int isls;
  445. {
  446.     HEADER *hp;
  447.     char *bp, *cp;
  448.     int n, n1, i, j, nmx, ancount, nscount, arcount, qdcount, buflen;
  449.     u_short pref, class;
  450.  
  451.     /*
  452.      * find first satisfactory answer
  453.      */
  454.     hp = (HEADER *) answer;
  455.     ancount = ntohs(hp->ancount);
  456.     qdcount = ntohs(hp->qdcount);
  457.     nscount = ntohs(hp->nscount);
  458.     arcount = ntohs(hp->arcount);
  459.     if (_res.options & RES_DEBUG || (verbose && isls == 0))
  460.         printf("rcode = %d (%s), ancount=%d\n", 
  461.                hp->rcode, DecodeError(hp->rcode), ancount);
  462.     if (hp->rcode != NOERROR || (ancount+nscount+arcount) == 0) {
  463.         switch (hp->rcode) {
  464.             case NXDOMAIN:
  465.                 /* Check if it's an authoritive answer */
  466.                 if (hp->aa) {
  467.                     h_errno = HOST_NOT_FOUND;
  468.                     return(0);
  469.                 } else {
  470.                     h_errno = TRY_AGAIN;
  471.                     return(0);
  472.                 }
  473.             case SERVFAIL:
  474.                 h_errno = TRY_AGAIN;
  475.                 return(0);
  476. #ifdef OLDJEEVES
  477.             /*
  478.              * Jeeves (TOPS-20 server) still does not
  479.              * support MX records.  For the time being,
  480.              * we must accept FORMERRs as the same as
  481.              * NOERROR.
  482.              */
  483.             case FORMERR:
  484. #endif OLDJEEVES
  485.             case NOERROR:
  486. /* TpB - set a return error for this case. NO_DATA */
  487.                 h_errno = NO_DATA;
  488.                 return(0); /* was 1,but now indicates exception */
  489. #ifndef OLDJEEVES
  490.             case FORMERR:
  491. #endif OLDJEEVES
  492.             case NOTIMP:
  493.             case REFUSED:
  494.                 h_errno = NO_RECOVERY;
  495.                 return(0);
  496.         }
  497.         return (0);
  498.     }
  499.     bp = hostbuf;
  500.     nmx = 0;
  501.     buflen = sizeof(hostbuf);
  502.     cp = (char *)answer + sizeof(HEADER);
  503.     if (qdcount) {
  504.         cp += dn_skipname(cp,eom) + QFIXEDSZ;
  505.         while (--qdcount > 0)
  506.             cp += dn_skipname(cp,eom) + QFIXEDSZ;
  507.     }
  508.     if (ancount) {
  509.       if (!hp->aa)
  510.         if (verbose && isls == 0)
  511.           printf("The following answer is not authoritative:\n");
  512.       while (--ancount >= 0 && cp && cp < eom) {
  513.         cp = pr_rr(cp, answer, stdout, filter);
  514. /*
  515.  * When we ask for address and there is a CNAME, it seems to return
  516.  * both the CNAME and the address.  Since we trace down the CNAME
  517.  * chain ourselves, we don't really want to print the address at
  518.  * this point.
  519.  */
  520.         if (cname && ! verbose)
  521.           return (1);
  522.       }
  523.     }
  524.     if (! verbose)
  525.       return (1);
  526.     if (nscount) {
  527.       printf("For authoritative answers, see:\n");
  528.       while (--nscount >= 0 && cp && cp < eom) {
  529.         cp = pr_rr(cp, answer, stdout, filter);
  530.       }
  531.     }
  532.     if (arcount) {
  533.       printf("Additional information:\n");
  534.       while (--arcount >= 0 && cp && cp < eom) {
  535.         cp = pr_rr(cp, answer, stdout, filter);
  536.       }
  537.     }
  538.     return(1);
  539.  }
  540.  
  541. static char cnamebuf[MAXDNAME];
  542.  
  543. /*
  544.  * Print resource record fields in human readable form.
  545.  */
  546. char *
  547. pr_rr(cp, msg, file, filter)
  548.     char *cp, *msg;
  549.     FILE *file;
  550.         int filter;
  551. {
  552.     int type, class, dlen, n, c, proto, ttl;
  553.     struct in_addr inaddr;
  554.     char *cp1;
  555.     struct protoent *protop;
  556.     struct servent *servp;
  557.     char punc;
  558.     int doprint;
  559.     char name[MAXDNAME];
  560.  
  561.     if ((cp = pr_cdname(cp, msg, name, sizeof(name))) == NULL)
  562.         return (NULL);            /* compression error */
  563.  
  564.     type = _getshort(cp);
  565.     cp += sizeof(u_short);
  566.  
  567.     class = _getshort(cp);
  568.     cp += sizeof(u_short);
  569.  
  570.     ttl = _getlong(cp);
  571.     cp += sizeof(u_long);
  572.  
  573.     if (filter == type || filter == T_ANY ||
  574.         (filter == T_A && (type == T_PTR || type == T_NS)))
  575.       doprint = 1;
  576.     else
  577.       doprint = 0;
  578.  
  579.     if (doprint)
  580.       if (verbose)
  581.         fprintf(file,"%s\t%d%s\t%s",
  582.             name, ttl, pr_class(class), pr_type(type));
  583.       else
  584.         fprintf(file,"%s%s %s",name, pr_class(class), pr_type(type));
  585.     if (verbose)
  586.       punc = '\t';
  587.     else
  588.       punc = ' ';
  589.  
  590.     dlen = _getshort(cp);
  591.     cp += sizeof(u_short);
  592.     cp1 = cp;
  593.     /*
  594.      * Print type specific data, if appropriate
  595.      */
  596.     switch (type) {
  597.     case T_A:
  598.         switch (class) {
  599.         case C_IN:
  600.             bcopy(cp, (char *)&inaddr, sizeof(inaddr));
  601.             if (dlen == 4) {
  602.                     if (doprint)
  603.                   fprintf(file,"%c%s", punc,
  604.                     inet_ntoa(inaddr));
  605.                 cp += dlen;
  606.             } else if (dlen == 7) {
  607.                     if (doprint) {
  608.                   fprintf(file,"%c%s", punc,
  609.                       inet_ntoa(inaddr));
  610.                   fprintf(file,", protocol = %d", cp[4]);
  611.                   fprintf(file,", port = %d",
  612.                       (cp[5] << 8) + cp[6]);
  613.                 }
  614.                 cp += dlen;
  615.             }
  616.             break;
  617.         }
  618.         break;
  619.     case T_CNAME:
  620.         if (dn_expand(msg, msg + 512, cp, cnamebuf, 
  621.                   sizeof(cnamebuf)) >= 0)
  622.           cname = cnamebuf;                
  623.     case T_MB:
  624. #ifdef OLDRR
  625.     case T_MD:
  626.     case T_MF:
  627. #endif /* OLDRR */
  628.     case T_MG:
  629.     case T_MR:
  630.     case T_NS:
  631.     case T_PTR:
  632.         cp = pr_cdname(cp, msg, name, sizeof(name));
  633.         if (doprint)
  634.           fprintf(file,"%c%s",punc, name);
  635.         break;
  636.  
  637.     case T_HINFO:
  638.         if (n = *cp++) {
  639.             if (doprint)
  640.               fprintf(file,"%c%.*s", punc, n, cp);
  641.             cp += n;
  642.         }
  643.         if (n = *cp++) {
  644.             if (doprint)
  645.               fprintf(file,"%c%.*s", punc, n, cp);
  646.             cp += n;
  647.         }
  648.         break;
  649.  
  650.     case T_SOA:
  651.         cp = pr_cdname(cp, msg, name, sizeof(name));
  652.         if (doprint)
  653.           fprintf(file,"\t%s", name);
  654.         cp = pr_cdname(cp, msg, name, sizeof(name));
  655.         if (doprint)
  656.           fprintf(file," %s", name);
  657.         if (doprint)
  658.           fprintf(file,"(\n\t\t\t%ld\t;serial (version)", _getlong(cp));
  659.         cp += sizeof(u_long);
  660.         if (doprint)
  661.           fprintf(file,"\n\t\t\t%ld\t;refresh period", _getlong(cp));
  662.         cp += sizeof(u_long);
  663.         if (doprint)
  664.           fprintf(file,"\n\t\t\t%ld\t;retry refresh this often", _getlong(cp));
  665.         cp += sizeof(u_long);
  666.         if (doprint)
  667.           fprintf(file,"\n\t\t\t%ld\t;expiration period", _getlong(cp));
  668.         cp += sizeof(u_long);
  669.         if (doprint)
  670.           fprintf(file,"\n\t\t\t%ld\t;minimum TTL\n\t\t\t)", _getlong(cp));
  671.         cp += sizeof(u_long);
  672.         break;
  673.  
  674.     case T_MX:
  675.         if (doprint)
  676.           if (verbose)
  677.             fprintf(file,"\t%ld ",_getshort(cp));
  678.           else
  679.             fprintf(file," ");
  680.         cp += sizeof(u_short);
  681.         cp = pr_cdname(cp, msg, name, sizeof(name));
  682.         if (doprint)
  683.           fprintf(file, "%s", name);
  684.         break;
  685.  
  686.     case T_MINFO:
  687.         cp = pr_cdname(cp, msg, name, sizeof(name));
  688.         if (doprint)
  689.           fprintf(file,"%c%s",punc, name);
  690.         cp = pr_cdname(cp, msg, name, sizeof(name));
  691.         if (doprint)
  692.           fprintf(file," %s", name);
  693.         break;
  694.  
  695.         /* Roy start */
  696.     case T_TXT:
  697.         if (doprint)
  698.           fprintf(file,"%c%.*s", punc, dlen, cp);
  699.         cp += dlen;
  700.         break;
  701.         /* Roy end */
  702.  
  703.     case T_UINFO:
  704.         if (doprint)
  705.           fprintf(file,"%c%s", punc, cp);
  706.         cp += dlen;
  707.         break;
  708.  
  709.     case T_UID:
  710.     case T_GID:
  711.         if (dlen == 4) {
  712.             if (doprint)
  713.               fprintf(file,"%c%ld", punc, _getlong(cp));
  714.             cp += sizeof(int);
  715.         }
  716.         break;
  717.  
  718.     case T_WKS:
  719.         if (dlen < sizeof(u_long) + 1)
  720.             break;
  721.         bcopy(cp, (char *)&inaddr, sizeof(inaddr));
  722.         cp += sizeof(u_long);
  723.         proto = *cp++;
  724.         protop = getprotobynumber(proto);
  725.         if (doprint)
  726.           if (protop)
  727.             fprintf(file,"%c%s %s", punc,
  728.                 inet_ntoa(inaddr), protop->p_name);
  729.           else
  730.             fprintf(file,"%c%s %d", punc,
  731.                 inet_ntoa(inaddr), proto);
  732.  
  733.         n = 0;
  734.         while (cp < cp1 + dlen) {
  735.             c = *cp++;
  736.             do {
  737.                  if (c & 0200) {
  738.                   servp = NULL;
  739.                   if (protop)
  740.                     servp = getservbyport (htons(n),
  741.                                protop->p_name);
  742.                   if (doprint)
  743.                     if (servp)
  744.                       fprintf(file, " %s", servp->s_name);
  745.                     else
  746.                       fprintf(file, " %d", n);
  747.                 }
  748.                  c <<= 1;
  749.             } while (++n & 07);
  750.         }
  751.         break;
  752.  
  753.     default:
  754.         if (doprint)
  755.           fprintf(file,"%c???", punc);
  756.         cp += dlen;
  757.     }
  758.     if (cp != cp1 + dlen)
  759.         fprintf(file,"packet size error (%#x != %#x)\n", cp, cp1+dlen);
  760.     if (doprint)
  761.       fprintf(file,"\n");
  762.     return (cp);
  763. }
  764.  
  765. static    char nbuf[20];
  766.  
  767. /*
  768.  * Return a string for the type
  769.  */
  770. char *
  771. pr_type(type)
  772.     int type;
  773. {
  774.     switch (type) {
  775.     case T_A:
  776.         return(verbose? "A" : "has address");
  777.     case T_NS:        /* authoritative server */
  778.         return("NS");
  779. #ifdef OLDRR
  780.     case T_MD:        /* mail destination */
  781.         return("MD");
  782.     case T_MF:        /* mail forwarder */
  783.         return("MF");
  784. #endif /* OLDRR */
  785.     case T_CNAME:        /* connonical name */
  786.         return(verbose? "CNAME" : "is a nickname for");
  787.     case T_SOA:        /* start of authority zone */
  788.         return("SOA");
  789.     case T_MB:        /* mailbox domain name */
  790.         return("MB");
  791.     case T_MG:        /* mail group member */
  792.         return("MG");
  793.     case T_MX:        /* mail routing info */
  794.         return(verbose? "MX" : "mail is handled by");
  795.     /* Roy start */
  796.     case T_TXT:        /* TXT - descriptive info */
  797.         return(verbose? "TXT" : "descriptive text");
  798.     /* Roy end */
  799.     case T_MR:        /* mail rename name */
  800.         return("MR");
  801.     case T_NULL:        /* null resource record */
  802.         return("NULL");
  803.     case T_WKS:        /* well known service */
  804.         return("WKS");
  805.     case T_PTR:        /* domain name pointer */
  806.         return("PTR");
  807.     case T_HINFO:        /* host information */
  808.         return("HINFO");
  809.     case T_MINFO:        /* mailbox information */
  810.         return("MINFO");
  811.     case T_AXFR:        /* zone transfer */
  812.         return("AXFR");
  813.     case T_MAILB:        /* mail box */
  814.         return("MAILB");
  815.     case T_MAILA:        /* mail address */
  816.         return("MAILA");
  817.     case T_ANY:        /* matches any type */
  818.         return("ANY");
  819.     case T_UINFO:
  820.         return("UINFO");
  821.     case T_UID:
  822.         return("UID");
  823.     case T_GID:
  824.         return("GID");
  825.     default:
  826.         return (sprintf(nbuf, "%d", type));
  827.     }
  828. }
  829.  
  830. /*
  831.  * Return a mnemonic for class
  832.  */
  833. char *
  834. pr_class(class)
  835.     int class;
  836. {
  837.  
  838.     switch (class) {
  839.     case C_IN:        /* internet class */
  840.         return(verbose? " IN" : "");
  841.     case C_HS:        /* internet class */
  842.         return(verbose? " HS" : "");
  843.     case C_ANY:        /* matches any class */
  844.         return(" ANY");
  845.     default:
  846.         return (sprintf(nbuf," %d", class));
  847.     }
  848. }
  849.  
  850. char *
  851. pr_cdname(cp, msg, name, namelen)
  852.     char *cp, *msg;
  853.         char *name;
  854.         int namelen;
  855. {
  856.     int n;
  857.  
  858.     if ((n = dn_expand(msg, msg + 512, cp, name, namelen - 2)) < 0)
  859.         return (NULL);
  860.     if (name[0] == '\0') {
  861.         name[0] = '.';
  862.         name[1] = '\0';
  863.     }
  864.     return (cp + n);
  865. }
  866.  
  867. char *resultcodes[] = {
  868.     "NOERROR",
  869.     "FORMERR",
  870.     "SERVFAIL",
  871.     "NXDOMAIN",
  872.     "NOTIMP",
  873.     "REFUSED",
  874.     "6",
  875.     "7",
  876.     "8",
  877.     "9",
  878.     "10",
  879.     "11",
  880.     "12",
  881.     "13",
  882.     "14",
  883.     "NOCHANGE",
  884. };
  885.  
  886.  
  887.  
  888. /*
  889.  ******************************************************************************
  890.  *
  891.  *  ListHosts --
  892.  *
  893.  *    Requests the name server to do a zone transfer so we
  894.  *    find out what hosts it knows about.
  895.  *
  896.  *  Results:
  897.  *    SUCCESS        the listing was successful.
  898.  *    ERROR        the server could not be contacted because 
  899.  *            a socket could not be obtained or an error
  900.  *            occured while receiving, or the output file
  901.  *            could not be opened.
  902.  *
  903.  ******************************************************************************
  904.  */
  905.  
  906. int
  907. ListHosts(namePtr, queryType)
  908.     char *namePtr;
  909.     int  queryType;  /* e.g. T_A */
  910. {
  911.     querybuf         buf, answer;
  912.     struct sockaddr_in     sin;
  913.     HEADER             *headerPtr;
  914.  
  915.     int             msglen;
  916.     int             amtToRead;
  917.     int             numRead;
  918.     int             i;
  919.     int             numAnswers = 0;
  920.     int             result;
  921.     int             soacnt = 0;
  922.     u_short         len;
  923.     int            dlen;
  924.     int            type;
  925.     int            nscount;
  926.     char             *cp, *nmp;
  927.     char             name[NAME_LEN];
  928.     char             dname[2][NAME_LEN];
  929.     char             domain[NAME_LEN];
  930. /* names and addresses of name servers to try */
  931. #define NUMNS 8
  932.     char            nsname[NUMNS][NAME_LEN];
  933.     int            nshaveaddr[NUMNS];
  934. #define IPADDRSIZE 4
  935. #define NUMNSADDR 16
  936.     char             nsipaddr[NUMNSADDR][IPADDRSIZE];
  937.     int            numns;
  938.     int            numnsaddr;
  939.     int            thisns;
  940.     struct hostent        *hp;
  941.     enum {
  942.         NO_ERRORS, 
  943.         ERR_READING_LEN, 
  944.         ERR_READING_MSG,
  945.         ERR_PRINTING,
  946.     } error = NO_ERRORS;
  947.  
  948. /*
  949.  * normalize to not have trailing dot.  We do string compares below
  950.  * of info from name server, and it won't have trailing dots.
  951.  */
  952.     i = strlen(namePtr);
  953.     if (namePtr[i-1] == '.')
  954.       namePtr[i-1] = 0;
  955.  
  956.     if (server_specified) {
  957.       bcopy(&_res.nsaddr.sin_addr, nsipaddr[0], IPADDRSIZE);
  958.       numnsaddr = 1;
  959.     }
  960.     else {
  961.  
  962. /*
  963.  * First we have to find out where to look.  This needs a NS query,
  964.  * possibly followed by looking up addresses for some of the names.
  965.  */
  966.  
  967.     msglen = res_mkquery(QUERY, namePtr, C_IN, T_NS,
  968.                 (char *)0, 0, (char *)0, 
  969.                 (char *) &buf, sizeof(buf));
  970.  
  971.     if (msglen < 0) {
  972.         printf("res_mkquery failed\n");
  973.         return (ERROR);
  974.     }
  975.  
  976.     msglen = res_send((char *)&buf,msglen,(char *)&answer, sizeof(answer));
  977.     
  978.     if (msglen < 0) {
  979.         printf("Unable to get to nameserver -- try again later\n");
  980.         return (ERROR);
  981.     }
  982.     if (_res.options & RES_DEBUG || verbose)
  983.         printf("rcode = %d (%s), ancount=%d\n", 
  984.                answer.qb1.rcode, DecodeError(answer.qb1.rcode),
  985.                ntohs(answer.qb1.ancount));
  986.  
  987. /*
  988.  * Analyze response to our NS lookup
  989.  */
  990.  
  991.     nscount = ntohs(answer.qb1.ancount) + ntohs(answer.qb1.nscount) +
  992.           ntohs(answer.qb1.arcount);
  993.  
  994.     if (answer.qb1.rcode != NOERROR || nscount == 0) {
  995.         switch (answer.qb1.rcode) {
  996.             case NXDOMAIN:
  997.                 /* Check if it's an authoritive answer */
  998.                 if (answer.qb1.aa) {
  999.                     printf("No such domain\n");
  1000.                 } else {
  1001.                     printf("Unable to get information about domain -- try again later.\n");
  1002.                 }
  1003.                 break;
  1004.             case SERVFAIL:
  1005.                 printf("Unable to get information about that domain -- try again later.\n");
  1006.                 break;
  1007.             case NOERROR:
  1008.                 printf("That domain exists, but seems to be a leaf node.\n");
  1009.                 break;
  1010.             case FORMERR:
  1011.             case NOTIMP:
  1012.             case REFUSED:
  1013.                 printf("Unrecoverable error looking up domain name.\n");
  1014.                 break;
  1015.         }
  1016.         return (0);
  1017.     }
  1018.  
  1019.     cp = answer.qb2 + sizeof(HEADER);
  1020.     if (ntohs(answer.qb1.qdcount) > 0)
  1021.       cp += dn_skipname(cp, answer.qb2 + msglen) + QFIXEDSZ;
  1022.  
  1023.     numns = 0;
  1024.     numnsaddr = 0;
  1025.  
  1026. /*
  1027.  * Look at response from NS lookup for NS and A records.
  1028.  */
  1029.  
  1030.     for (;nscount; nscount--) {
  1031.       cp += dn_expand(answer.qb2, answer.qb2 + msglen, cp,
  1032.               domain, sizeof(domain));
  1033.       type = _getshort(cp);
  1034.       cp += sizeof(u_short) + sizeof(u_short) + sizeof(u_long);
  1035.       dlen = _getshort(cp);
  1036.       cp += sizeof(u_short);
  1037.       if (type == T_NS) {
  1038.         if (dn_expand(answer.qb2, answer.qb2 + msglen, cp, 
  1039.               name, sizeof(name)) >= 0) {
  1040.           if (numns < NUMNS && strcasecmp(domain, namePtr) == 0) {
  1041.         for (i = 0; i < numns; i++)
  1042.           if (strcasecmp(nsname[i], name) == 0)
  1043.             break;  /* duplicate */
  1044.         if (i >= numns) {
  1045.           strncpy(nsname[numns], name, sizeof(name));
  1046.           nshaveaddr[numns] = 0;
  1047.           numns++;
  1048.         }
  1049.           }
  1050.         }
  1051.       }
  1052.       else if (type == T_A) {
  1053.         if (numnsaddr < NUMNSADDR)
  1054.           for (i = 0; i < numns; i++) {
  1055.         if (strcasecmp(nsname[i], domain) == 0) {
  1056.           nshaveaddr[i]++;
  1057.           bcopy(cp, nsipaddr[numnsaddr],IPADDRSIZE);
  1058.           numnsaddr++;
  1059.           break;
  1060.         }
  1061.           }
  1062.       }
  1063.       cp += dlen;
  1064.     }
  1065.  
  1066. /*
  1067.  * Usually we'll get addresses for all the servers in the additional
  1068.  * info section.  But in case we don't, look up their addresses.
  1069.  */
  1070.  
  1071.     for (i = 0; i < numns; i++) {
  1072.       if (! nshaveaddr[i]) {
  1073.         register long **hptr;
  1074.         int numaddrs = 0;
  1075.  
  1076.         hp = gethostbyname(nsname[i]);
  1077.         if (hp) {
  1078.           for (hptr = (long **)hp->h_addr_list; *hptr; hptr++)
  1079.         if (numnsaddr < NUMNSADDR) {
  1080.           bcopy((char *)*hptr, nsipaddr[numnsaddr],IPADDRSIZE);
  1081.           numnsaddr++;
  1082.           numaddrs++;
  1083.         }
  1084.         }
  1085.         if (_res.options & RES_DEBUG || verbose)
  1086.           printf("Found %d addresses for %s by extra query\n",
  1087.              numaddrs, nsname[i]);
  1088.       }
  1089.       else
  1090.         if (_res.options & RES_DEBUG || verbose)
  1091.           printf("Found %d addresses for %s\n",
  1092.              nshaveaddr[i], nsname[i]);
  1093.     }
  1094.         }
  1095. /*
  1096.  * Now nsipaddr has numnsaddr addresses for name servers that
  1097.  * serve the requested domain.  Now try to find one that will
  1098.  * accept a zone transfer.
  1099.  */
  1100.  
  1101.     thisns = 0;
  1102.  
  1103. again:
  1104.  
  1105.     numAnswers = 0;
  1106.     soacnt = 0;
  1107.  
  1108.     /*
  1109.      *  Create a query packet for the requested domain name.
  1110.      *
  1111.      */
  1112.     msglen = res_mkquery(QUERY, namePtr, getclass, T_AXFR,
  1113.                 (char *)0, 0, (char *)0, 
  1114.                 (char *) &buf, sizeof(buf));
  1115.     if (msglen < 0) {
  1116.         if (_res.options & RES_DEBUG) {
  1117.         fprintf(stderr, "ListHosts: Res_mkquery failed\n");
  1118.         }
  1119.         return (ERROR);
  1120.     }
  1121.  
  1122.     bzero((char *)&sin, sizeof(sin));
  1123.     sin.sin_family    = AF_INET;
  1124.     sin.sin_port    =  htons(NAMESERVER_PORT);
  1125.  
  1126.     /*
  1127.      *  Set up a virtual circuit to the server.
  1128.      */
  1129.  
  1130.     for (;thisns < numnsaddr; thisns++) {
  1131.       if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  1132.         perror("ListHosts");
  1133.         return(ERROR);
  1134.       }
  1135.       bcopy(nsipaddr[thisns], &sin.sin_addr, IPADDRSIZE);
  1136.       if (_res.options & RES_DEBUG || verbose)
  1137.         printf("Trying %s\n", inet_ntoa(sin.sin_addr));
  1138.       if (connect(sockFD, &sin, sizeof(sin)) >= 0)
  1139.         break;
  1140.       if (verbose)
  1141.         perror("Connection failed, trying next server");
  1142.       (void) close(sockFD);
  1143.       sockFD = -1;
  1144.     }    
  1145.     if (thisns >= numnsaddr) {
  1146.       printf("No server for that domain responded\n");
  1147.       if (!verbose)
  1148.         perror("Error from the last server was");
  1149.       return(ERROR);
  1150.     }
  1151.  
  1152.     /*
  1153.      * Send length & message for zone transfer 
  1154.      */
  1155.  
  1156.         len = htons(msglen);
  1157.  
  1158.         if (write(sockFD, (char *)&len, sizeof(len)) != sizeof(len) ||
  1159.             write(sockFD, (char *) &buf, msglen) != msglen) {
  1160.         perror("ListHosts");
  1161.         (void) close(sockFD);
  1162.         sockFD = -1;
  1163.         return(ERROR);
  1164.     }
  1165.  
  1166.     filePtr = stdout;
  1167.  
  1168.     while (1) {
  1169.  
  1170.         /*
  1171.          * Read the length of the response.
  1172.          */
  1173.  
  1174.         cp = (char *) &buf;
  1175.         amtToRead = sizeof(u_short);
  1176.         while(amtToRead > 0 && (numRead = read(sockFD, cp, amtToRead)) > 0){
  1177.         cp       += numRead;
  1178.         amtToRead -= numRead;
  1179.         }
  1180.         if (numRead <= 0) {
  1181.         error = ERR_READING_LEN;
  1182.         break;
  1183.         }    
  1184.  
  1185.         if ((len = htons(*(u_short *)&buf)) == 0) {
  1186.         break;    /* nothing left to read */
  1187.         }
  1188.  
  1189.         /*
  1190.          * Read the response.
  1191.          */
  1192.  
  1193.         amtToRead = len;
  1194.         cp = (char *) &buf;
  1195.         while(amtToRead > 0 && (numRead = read(sockFD, cp, amtToRead)) > 0){
  1196.         cp += numRead;
  1197.         amtToRead -= numRead;
  1198.         }
  1199.         if (numRead <= 0) {
  1200.         error = ERR_READING_MSG;
  1201.         break;
  1202.         }
  1203.  
  1204.         i = buf.qb1.rcode;
  1205.         if (i != NOERROR || ntohs(buf.qb1.ancount) == 0) {
  1206.           if ((thisns+1) < numnsaddr &&
  1207.           (i == SERVFAIL || i == NOTIMP || i == REFUSED)) {
  1208.         if (_res.options & RES_DEBUG || verbose)
  1209.           printf("Server failed, trying next server: %s\n",
  1210.              i != NOERROR ? 
  1211.              DecodeError(i) : "Premature end of data");
  1212.         (void) close(sockFD);
  1213.         sockFD = -1;
  1214.         thisns++;
  1215.         goto again;
  1216.           }
  1217.           printf("Server failed: %s\n",
  1218.              i != NOERROR ? DecodeError(i) : "Premature end of data");
  1219.           break;
  1220.         }
  1221.  
  1222.  
  1223.         result = printinfo(&buf, cp, queryType, 1);
  1224.         if (! result) {
  1225.         error = ERR_PRINTING;
  1226.         break;
  1227.         }
  1228.         numAnswers++;
  1229.         cp = buf.qb2 + sizeof(HEADER);
  1230.         if (ntohs(buf.qb1.qdcount) > 0)
  1231.         cp += dn_skipname(cp, buf.qb2 + len) + QFIXEDSZ;
  1232.  
  1233.         nmp = cp;
  1234.         cp += dn_skipname(cp, (u_char *)&buf + len);
  1235.         if ((_getshort(cp) == T_SOA)) {
  1236.         dn_expand(buf.qb2, buf.qb2 + len, nmp, dname[soacnt],
  1237.             sizeof(dname[0]));
  1238.             if (soacnt) {
  1239.             if (strcmp(dname[0], dname[1]) == 0)
  1240.             break;
  1241.         } else
  1242.             soacnt++;
  1243.         }
  1244.         }
  1245.  
  1246.     (void) close(sockFD);
  1247.     sockFD = -1;
  1248.  
  1249.     switch (error) {
  1250.         case NO_ERRORS:
  1251.         return (SUCCESS);
  1252.  
  1253.         case ERR_READING_LEN:
  1254.         return(ERROR);
  1255.  
  1256.         case ERR_PRINTING:
  1257.         fprintf(stderr,"*** Error during listing of %s: %s\n", 
  1258.                 namePtr, DecodeError(result));
  1259.         return(result);
  1260.  
  1261.         case ERR_READING_MSG:
  1262.         headerPtr = (HEADER *) &buf;
  1263.         fprintf(stderr,"ListHosts: error receiving zone transfer:\n");
  1264.         fprintf(stderr,
  1265.            "  result: %s, answers = %d, authority = %d, additional = %d\n", 
  1266.                 resultcodes[headerPtr->rcode], 
  1267.                 ntohs(headerPtr->ancount), ntohs(headerPtr->nscount), 
  1268.             ntohs(headerPtr->arcount));
  1269.         return(ERROR);
  1270.         default:
  1271.         return(ERROR);
  1272.     }
  1273. }
  1274.  
  1275. char *
  1276. DecodeError(result)
  1277.     int result;
  1278. {
  1279.     switch(result) {
  1280.         case NOERROR:     return("Success"); break;
  1281.         case FORMERR:    return("Format error"); break;
  1282.         case SERVFAIL:    return("Server failed"); break;
  1283.         case NXDOMAIN:    return("Non-existent domain"); break;
  1284.         case NOTIMP:    return("Not implemented"); break;
  1285.         case REFUSED:    return("Query refused"); break;
  1286.         case NOCHANGE:    return("No change"); break;
  1287.         case NO_INFO:     return("No information"); break;
  1288.         case ERROR:     return("Unspecified error"); break;
  1289.         case TIME_OUT:     return("Timed out"); break;
  1290.         case NONAUTH:     return("Non-authoritative answer"); break;
  1291.         default:         break;
  1292.     }
  1293.     return("BAD ERROR VALUE"); 
  1294. }
  1295.  
  1296.